<?php

namespace Biz\service\SuperSubsidy;

use Biz\model\SuperSubsidy\YouZanDeliverRecordModel;
use Biz\model\SuperSubsidy\YouZanOrders;
use Doraemon\tools\Log;
use Doraemon\tools\Youzan;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\IOFactory;


class YouZanDeliver implements ConstInterface
{

    private static $deliverDebug = false;

    /**
     * 批量发货
     * @param $file
     * @return void
     */
    public static function batchOrderDeliver($brandUserId, $file)
    {
        $allExpress = json_decode(self::YOU_ZAN_EXPRESS_NAME_MAP, 2);
        $spreadsheet = IOFactory::load($file);
        $spreadsheet->setActiveSheetIndex(0);
        $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
        $rowNum = 1;
        $data = [];
        $sendNum = 0;
        foreach ($sheetData as $row) {
            if ($rowNum >= 2) {
                $item = [
                    'tid' => trim($row['A']),
                    'oid' => trim($row['B']),
                    'express_name' => trim($row['C']),
                    'express_no' => trim($row['D']),
                ];
                $item['express_id'] = $allExpress[$item['express_name']] ?? '';
                $fullData = true;
                foreach ($item as $key => $value) {
                    if (empty($value)) {
                        $fullData = false;
                        break;
                    }
                }
                if ($fullData) {
                    $sendNum++;
                    $data[$item['tid']][$item['express_id'] . '-' . $item['express_no']]['express_no'] = $item['express_no'];
                    $data[$item['tid']][$item['express_id'] . '-' . $item['express_no']]['express_name'] = $item['express_name'];
                    $data[$item['tid']][$item['express_id'] . '-' . $item['express_no']]['express_id'] = $item['express_id'];
                    $data[$item['tid']][$item['express_id'] . '-' . $item['express_no']]['oids'][] = $item['oid'];
                } else {
                    self::logDeliverData('获取到第' . $rowNum . '行数据有空数据', $item);
                }
            }
            $rowNum++;
        }
        if ($sendNum > 100) {
            throw new \Exception('单次批量发货最大支持100条，请分多次操作');
        }
        $sendDesc = [];
        foreach ($data as $tid => $row) {
            foreach ($row as $key => $item) {
                $expressId = $item['express_id'];
                $expressNo = $item['express_no'];
                $oids = $item['oids'];
                $sendMessage = [
                    'tid' => $tid,
                    'ex_id' => $expressId,
                    'ex_no' => $expressNo,
                    'oids' => $oids
                ];
                $sendDesc[] = $sendMessage;
            }
        }
        if ($sendDesc) {
            $res = YouZanDeliverRecordModel::insertData([
                    'record_no' => YouZanDeliverRecordModel::genRecordNo($brandUserId, YouZanDeliverRecordModel::TYPE_SEND),
                    'type' => YouZanDeliverRecordModel::TYPE_SEND,
                    'brand_user_id' => $brandUserId,
                    'send_num' => $sendNum,
                    'success_num' => 0,
                    'status' => YouZanDeliverRecordModel::STATUS_CREATE,
                    'desc' => json_encode($sendDesc, JSON_UNESCAPED_UNICODE),
                ]
            );
            self::logDeliverData('添加发货记录sql', YouZanDeliverRecordModel::log());
        } else {
            throw new \Exception('没有任务要发货的数据');
        }
        return $res;
    }

    /**
     * 单个发货
     * @param $brandUserId
     * @param $tid
     * @param $oid
     * @param $expressId
     * @param $expressNo
     * @return true
     * @throws \Exception
     */
    public static function OrderDeliver($brandUserId, $tid, $oid, $expressId, $expressNo)
    {
        $sendMessage = [
            'tid' => $tid,
            'ex_id' => $expressId,
            'ex_no' => $expressNo,
            'oids' => [$oid]
        ];
        $sendDesc[] = $sendMessage;

        $recordNo = YouZanDeliverRecordModel::genRecordNo($brandUserId, YouZanDeliverRecordModel::TYPE_SEND);
        $res = YouZanDeliverRecordModel::insertData([
                'record_no' => $recordNo,
                'type' => YouZanDeliverRecordModel::TYPE_SEND,
                'brand_user_id' => $brandUserId,
                'send_num' => 1,
                'success_num' => 0,
                'status' => YouZanDeliverRecordModel::STATUS_CREATE,
                'desc' => json_encode($sendDesc, JSON_UNESCAPED_UNICODE),
            ]
        );
        self::logDeliverData('添加发货记录sql', YouZanDeliverRecordModel::log());

        if (!$res) {
            throw new \Exception('发货失败');
        }
        //操作发货
        $returnErrMsg = YouZanDeliver::handleDeliverRecord(false, $recordNo);
        $returnErrMsg = $returnErrMsg[0] ? $returnErrMsg[0] : [];
        if ($returnErrMsg && $returnErrMsg[$tid] && $returnErrMsg[$tid]['message']) {
            throw new \Exception($returnErrMsg[$tid]['message']);
        }
        return true;
    }

    /**
     * 修改物流
     * @param $brandUserId
     * @param $file
     * @return array
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public static function batchChangeOrderDeliver($brandUserId, $file)
    {
        $allExpress = json_decode(self::YOU_ZAN_EXPRESS_NAME_MAP, 2);
        $spreadsheet = IOFactory::load($file);
        $spreadsheet->setActiveSheetIndex(0);
        $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
        $rowNum = 1;
        $data = [];
        $oids = [];
        $sendNum = 0;
        foreach ($sheetData as $row) {
            if ($rowNum >= 2) {
                $item = [
                    'tid' => trim($row['A']),
                    'oid' => trim($row['B']),
                    'express_name' => trim($row['C']),
                    'express_no' => trim($row['D']),
                ];
                $item['express_id'] = $allExpress[$item['express_name']] ?? '';
                $fullData = true;
                foreach ($item as $key => $value) {
                    if (empty($value)) {
                        $fullData = false;
                        break;
                    }
                }
                if ($fullData) {
                    $oids[] = $item['oid'];
                    $sendNum++;
                    $data[$item['tid']][] = $item;
                } else {
                    self::logDeliverData('获取到第' . $rowNum . '行数据有空数据', $item);
                }
            }
            $rowNum++;
        }
        if ($sendNum > 100) {
            throw new \Exception('单次批量修改物流信息最大支持100条，请分多次操作');
        }
        $ordersList = $oids ? YouZanOrders::selectByWhere(['oid' => $oids], ['oid', 'dist_id']) : [];
        $ordersList = $ordersList ? array_column($ordersList, null, 'oid') : [];
        if (empty($oids) || empty($ordersList)) {
            throw new \Exception('没有订单的包裹记录');
        }
        foreach ($oids as $oid) {
            if (!isset($ordersList[$oid]) || !isset($ordersList[$oid]['dist_id']) || empty($ordersList[$oid]['dist_id'])) {
                throw new \Exception('没有订单商品明细:' . $oid . '的包裹记录');
            }
        }
        $sendDesc = [];
        foreach ($data as $tid => $rows) {
            $modify = [];
            foreach ($rows as $item) {
                $modify[] = [
                    'oid' => $item['oid'],
                    'dist_id' => $ordersList[$oid]['dist_id'],
                    'ex_no' => $item['express_no'],
                    'ex_id' => (int)$item['express_id'],
                ];
            }
            $sendDesc[] = [
                'tid' => $tid,
                'modify' => $modify,
            ];
        }
        if ($sendDesc) {
            $res = YouZanDeliverRecordModel::insertData([
                    'record_no' => YouZanDeliverRecordModel::genRecordNo($brandUserId, YouZanDeliverRecordModel::TYPE_CHANGE),
                    'type' => YouZanDeliverRecordModel::TYPE_CHANGE,
                    'brand_user_id' => $brandUserId,
                    'send_num' => $sendNum,
                    'success_num' => 0,
                    'status' => YouZanDeliverRecordModel::STATUS_CREATE,
                    'desc' => json_encode($sendDesc, JSON_UNESCAPED_UNICODE),
                ]
            );
            self::logDeliverData('添加更改物流记录sql', YouZanDeliverRecordModel::log());
        } else {
            throw new \Exception('没有任务要更改物流的数据');
        }
        return $res;
    }

    /**
     * 单个更改物流信息
     * @param $brandUserId
     * @param $tid
     * @param $oid
     * @param $expressId
     * @param $expressNo
     * @return true
     * @throws \Exception
     */
    public static function ChangeOrderDeliver($brandUserId, $tid, $oid, $expressId, $expressNo)
    {
        $oids = [$oid];
        $ordersList = YouZanOrders::selectByWhere(['oid' => $oids], ['oid', 'dist_id']);
        $ordersList = $ordersList ? array_column($ordersList, null, 'oid') : [];
        if (empty($oids) || empty($ordersList)) {
            throw new \Exception('没有订单的包裹记录');
        }
        foreach ($oids as $oid) {
            if (!isset($ordersList[$oid]) || !isset($ordersList[$oid]['dist_id']) || empty($ordersList[$oid]['dist_id'])) {
                throw new \Exception('没有订单商品明细:' . $oid . '的包裹记录');
            }
        }

        $modify[] = [
            'oid' => $oid,
            'dist_id' => $ordersList[$oid]['dist_id'],
            'ex_no' => (string)$expressNo,
            'ex_id' => (int)$expressId,
        ];
        $sendDesc[] = [
            'tid' => $tid,
            'modify' => $modify,
        ];

        $recordNo = YouZanDeliverRecordModel::genRecordNo($brandUserId, YouZanDeliverRecordModel::TYPE_CHANGE);
        $res = YouZanDeliverRecordModel::insertData([
                'record_no' => $recordNo,
                'type' => YouZanDeliverRecordModel::TYPE_CHANGE,
                'brand_user_id' => $brandUserId,
                'send_num' => 1,
                'success_num' => 0,
                'status' => YouZanDeliverRecordModel::STATUS_CREATE,
                'desc' => json_encode($sendDesc, JSON_UNESCAPED_UNICODE),
            ]
        );
        self::logDeliverData('添加更改物流记录sql', YouZanDeliverRecordModel::log());

        if (!$res) {
            throw new \Exception('发货失败');
        }
        //操作发货
        $returnErrMsg = YouZanDeliver::handleDeliverRecord(false, $recordNo);
        $returnErrMsg = $returnErrMsg[0] ? $returnErrMsg[0] : [];
        if ($returnErrMsg && $returnErrMsg[$tid] && $returnErrMsg[$tid]['message']) {
            throw new \Exception($returnErrMsg[$tid]['message']);
        }
        return true;
    }

    /**
     * 导出待发货订单
     * @return void
     */
    public static function exportWaitDeliverOrder($brandUserId)
    {
        //导出待发货订单，订单列表的订单筛选 未发货&退款状态为空和退款关闭的
        $params = [
            'is_deliver_goods' => 0,
            'refund_state' => [0, 50]
        ];
        YouZanOrder::exportOrderData($brandUserId, $params, '待发货订单');
    }

    public static function getDeliverRecord($brandUserId, $page = 1, $pageSize = 20, $params = [])
    {
        $where = [
            'brand_user_id' => $brandUserId,
            'LIMIT' => [($page - 1) * $pageSize, $pageSize],
            'ORDER' => ['id' => 'DESC'],
        ];
        if (is_null($brandUserId)) {
            unset($where['brand_user_id']);
        }
        $where = array_merge($where, $params);
        $res = YouZanDeliverRecordModel::selectByWhere($where, ['id', 'record_no', 'type', 'brand_user_id', 'created_at', 'send_num', 'success_num', 'status']);
        unset($where['LIMIT']);
        unset($where['ORDER']);
        $count = YouZanDeliverRecordModel::selectCountWhere($where);
        $isOver = ($page * $pageSize >= $count) ? 1 : 0;
        $list = [];
        foreach ($res as $row) {
            $operate = '';
            if ($row['status'] == YouZanDeliverRecordModel::STATUS_DONE) {
                $operate = ($row['send_num'] == $row['success_num']) ? '下载发货记录' : '查看失败原因';
            }
            $list[] = [
                'id' => $row['id'],
                'record_no' => $row['record_no'],
                'type' => $row['type'],
                'brand_user_id' => $row['brand_user_id'],
                'created_at' => $row['created_at'],
                'send_num' => $row['send_num'],
                'success_num' => $row['success_num'],
                'status' => $row['status'],
                'status_str' => (YouZanDeliverRecordModel::STATUS_DONE == $row['status']) ? '已完成' : '处理中',
                'operate' => $operate
            ];
        }
        return ['list' => $list, 'total' => $count, 'is_over' => $isOver];
    }

    /**
     * 导出发货记录
     * @param $recordNo 发货记录编号
     * @return void
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public static function exportDeliverRecord($recordNo)
    {
        $allExpress = json_decode(self::YOU_ZAN_EXPRESS, true);
        $info = YouZanDeliverRecordModel::getByWhere(['record_no' => $recordNo]);
        $descArr = ($info && $info['desc']) ? json_decode($info['desc'], true) : [];
        $allOids = [];
        $data = [];
        if ($descArr) {

            foreach ($descArr as $row) {
                if (YouZanDeliverRecordModel::TYPE_SEND == $info['type']) {
                    $oids = $row['oids'];
                    $allOids = array_merge($allOids, $oids);
                    foreach ($oids as $oid) {
                        $data[$oid] = [
                            'tid' => $row['tid'],
                            'oid' => $oid,
                            'express_id' => $row['ex_id'],
                            'express_name' => $allExpress[$row['ex_id']] ?? '',
                            'express_no' => $row['ex_no'],
                            'success' => $row['success'] ?? false,
                            'message' => $row['message'] ?? '',
                            'result' => '',
                            'num' => 0,
                            'item_barcode' => '',
                            'item_id' => '',
                        ];
                    }
                } else if (YouZanDeliverRecordModel::TYPE_CHANGE == $info['type']) {
                    foreach ($row['modify'] as $modify) {
                        $oid = $modify['oid'];
                        $data[$oid] = [
                            'tid' => $row['tid'],
                            'oid' => $oid,
                            'express_id' => $modify['ex_id'],
                            'express_name' => $allExpress[$modify['ex_id']] ?? '',
                            'express_no' => $modify['ex_no'],
                            'success' => $row['success'] ?? false,
                            'message' => $row['message'] ?? '',
                            'result' => '',
                            'num' => 0,
                            'item_barcode' => '',
                            'item_id' => '',
                        ];
                    }
                }
            }
        }
        $orderList = [];
        if ($allOids) {
            $orderList = YouZanOrders::selectByWhere(['oid' => $allOids], ['tid', 'oid', 'item_id', 'item_barcode', 'num']);
            $orderList = $orderList ? array_column($orderList, null, 'oid') : [];
        }
        foreach ($data as $oid => $row) {
            $data[$oid]['num'] = $orderList[$oid]['num'] ?? 0;
            $data[$oid]['item_id'] = $orderList[$oid]['item_id'] ?? '';
            $data[$oid]['item_barcode'] = $orderList[$oid]['item_barcode'] ?? '';
            $data[$oid]['result'] = ($row['success'] == true) ? 'SUCCESS' : 'FAIL';
            $data[$oid]['message'] = ($row['success'] == true) ? '处理成功' : $row['message'];
        }
        $sheetData = [
            ['cell_title' => '订单编号', 'cell_key' => 'A', 'cell_width' => 30, 'value_key' => 'tid'],
            ['cell_title' => '订单明细id', 'cell_key' => 'B', 'cell_width' => 30, 'value_key' => 'oid'],
            ['cell_title' => '物流公司', 'cell_key' => 'C', 'cell_width' => 20, 'value_key' => 'express_name'],
            ['cell_title' => '物流单号', 'cell_key' => 'D', 'cell_width' => 20, 'value_key' => 'express_no'],
            ['cell_title' => '商品条码', 'cell_key' => 'E', 'cell_width' => 30, 'value_key' => 'item_barcode'],
            ['cell_title' => '数量', 'cell_key' => 'F', 'cell_width' => 20, 'value_key' => 'num'],
            ['cell_title' => '处理结果', 'cell_key' => 'G', 'cell_width' => 20, 'value_key' => 'result'],
            ['cell_title' => '描述', 'cell_key' => 'H', 'cell_width' => 30, 'value_key' => 'message'],
        ];
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        foreach ($sheetData as $row) {
            $sheet->setCellValue($row['cell_key'] . '1', $row['cell_title']);
            $sheet->getColumnDimension($row['cell_key'])->setWidth($row['cell_width']);
            $styleArray = [
                'alignment' => [
                    'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                    'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
                ],
            ];
            $sheet->getStyle($row['cell_key'] . '1')->applyFromArray($styleArray);
        }
        $rowNum = 2; // 从第二行开始
        foreach ($data as $info) {
            foreach ($sheetData as $row) {
                $key = $row['value_key'];
                $value = isset($info[$key]) ? $info[$key] : '';
                $cellKey = $row['cell_key'] . $rowNum;
                $sheet->setCellValue($cellKey, $value);
                $styleArray = [
                    'alignment' => [
                        'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                        'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
                    ],
                ];
                $sheet->getStyle($cellKey)->applyFromArray($styleArray);
                $sheet->getCell($cellKey)->setValueExplicit($value, DataType::TYPE_STRING);
            }
            $rowNum++;
        }
        $fileName = $recordNo . '.xlsx';
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $fileName . '"');
        header('Cache-Control: max-age=0');
        header('Cache-Control: max-age=1');
        header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
        header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
        header('Pragma: public'); // HTTP/1.0
        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');

    }


    public static function handleDeliverRecord($debug = false, $recordNo = '')
    {
        $returnErrMsg = [];
        self::$deliverDebug = $debug;
        $where = [
            'status' => YouZanDeliverRecordModel::STATUS_CREATE,
            'ORDER' => ['id' => 'ASC']
        ];
        if ($recordNo) {
            $where['record_no'] = $recordNo;
            $where['status'] = [YouZanDeliverRecordModel::STATUS_CREATE, YouZanDeliverRecordModel::STATUS_DOING];
        }
        $list = YouZanDeliverRecordModel::selectByWhere($where);
        $ids = array_column($list, 'id');
        if (!empty($list) && !empty($ids)) {
            YouZanDeliverRecordModel::updateData(['status' => YouZanDeliverRecordModel::STATUS_DOING], ['id' => $ids]);
        }
        self::logDeliverData('查询到' . count($list) . '条待处理的发货记录');
        foreach ($list as $row) {
            if (YouZanDeliverRecordModel::TYPE_SEND == $row['type']) {
                list($result, $errMsg) = self::handleDeliverSendRecord($row);
                if ($errMsg) {
                    $returnErrMsg[] = $errMsg;
                    self::logDeliverData('发货失败', $errMsg);
                }
            } else if (YouZanDeliverRecordModel::TYPE_CHANGE == $row['type']) {
                list($result, $errMsg) = self::handleDeliverChangeRecord($row);
                if ($errMsg) {
                    $returnErrMsg[] = $errMsg;
                    self::logDeliverData('更改物流失败', $errMsg);
                }
            }
        }
        return $returnErrMsg;
    }

    private static function handleDeliverSendRecord($info)
    {
        $result = true;
        self::logDeliverData('处理发货记录:' . $info['record_no'] . '#id:' . $info['id']);
        $descArr = $info['desc'] ? json_decode($info['desc'], true) : [];
        $successNum = 0;
        $errMessage = [];
        $descData = [];
        $tids = [];
        if ($descArr) {
            foreach ($descArr as $row) {
                $tid = $row['tid'];
                $expressId = $row['ex_id'];
                $expressNo = $row['ex_no'];
                $oids = $row['oids'];
                $tids[] = $tid;
                $res = Youzan::OrderDeliver($tid, $expressId, $expressNo, $oids);
                self::logDeliverData('处理发货记录:' . $info['record_no'] . '#id:' . $info['id'] . ',API返回的结果', [
                    'request' => ['tid' => $tid, 'express_id' => $expressId, 'express_no' => $expressNo, 'oids' => $oids],
                    'response' => $res
                ]);
                if ($res['code'] == 200) {
                    $row['success'] = true;
                    $successNum = $successNum + count($oids);
                } else {
                    $row['success'] = false;
                    $errMessage[$tid] = $res;
                }
                $row['message'] = $res['message'];
                $descData[] = $row;
            }
        }
        if (!empty($errMessage)) {
            $result = false;
        }
        if ($descData) {
            YouZanDeliverRecordModel::updateData([
                'status' => YouZanDeliverRecordModel::STATUS_DONE,
                'success_num' => $successNum,
                'desc' => json_encode($descData, JSON_UNESCAPED_UNICODE)
            ], ['id' => $info['id']]);
            self::logDeliverData('处理发货记录:' . $info['record_no'] . '#id:' . $info['id'] . '已完成', YouZanDeliverRecordModel::log());
            YouZanOrder::_async_updateOrder($tids);
        }
        return [$result, $errMessage];
    }

    private static function handleDeliverChangeRecord($info)
    {
        $result = true;
        self::logDeliverData('处理修改物流记录:' . $info['record_no']);
        $descArr = $info['desc'] ? json_decode($info['desc'], true) : [];
        $successNum = 0;
        $errMessage = [];
        $descData = [];
        $tids = [];
        if ($descArr) {
            foreach ($descArr as $row) {
                $tid = $row['tid'];
                $tids[] = $tid;
                list($msec, $sec) = explode(' ', microtime());
                $mesctime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
                $modify = [];
                foreach ($row['modify'] as $modifyItem) {
                    $modify[] = [
                        'dist_id' => $modifyItem['dist_id'],
                        'express_no' => $modifyItem['ex_no'],
                        'express_id' => (int)$modifyItem['ex_id'],
                        'version' => $mesctime
                    ];
                }
                $res = Youzan::OrderDeliverUpdate($tid, $modify);
                self::logDeliverData('处理修改物流记录:' . $info['record_no'] . ',API返回的结果', [
                    'request' => ['tid' => $tid, 'modify' => $modify],
                    'response' => $res
                ]);
                if ($res['code'] == 200) {
                    $row['success'] = true;
                    $successNum = $successNum + count($modify);
                } else {
                    $row['success'] = false;
                    $errMessage[$tid] = $res;
                }
                $row['message'] = $res['message'];
                $descData[] = $row;
            }
        }
        if (!empty($errMessage)) {
            $result = false;
        }
        if ($descData) {
            YouZanDeliverRecordModel::updateData([
                'status' => YouZanDeliverRecordModel::STATUS_DONE,
                'success_num' => $successNum,
                'desc' => json_encode($descData, JSON_UNESCAPED_UNICODE)
            ], ['id' => $info['id']]);
            self::logDeliverData('处理发货记录:' . $info['record_no'] . '已完成', YouZanDeliverRecordModel::log());
            YouZanOrder::_async_updateOrder($tids);
        }
        return [$result, $errMessage];
    }

    private static function logDeliverData($message, array $data = [])
    {
        $msg = date('YmdHis') . '有赞发货日志｜' . $message;
        if (self::$deliverDebug) {
            $msg .= $data ? ('#' . json_encode($data, JSON_UNESCAPED_UNICODE)) : '';
            var_dump($msg);
        }
        Log::info($msg, $data);
    }

}